<template><div><h2 id="spring-boot-流式返回" tabindex="-1"><a class="header-anchor" href="#spring-boot-流式返回"><span>spring boot 流式返回</span></a></h2>
<p>使用sse协议进行流式返回。<br>
sse协议是一个基于http协议的轻量级协议<br>
<strong>返回报文规范：</strong></p>
<ul>
<li>Content-Type: text/event-stream：指定响应内容为事件流。</li>
<li>Cache-Control: no-cache：禁用缓存，确保客户端每次都能接收到最新的数据。</li>
<li>Connection: keep-alive：保持长连接，服务器可以持续推送数据。</li>
</ul>
<h2 id="http2与http1-1有什么区别" tabindex="-1"><a class="header-anchor" href="#http2与http1-1有什么区别"><span>http2与http1.1有什么区别</span></a></h2>
<h3 id="http1-0" tabindex="-1"><a class="header-anchor" href="#http1-0"><span>http1.0</span></a></h3>
<p>发送一个请求就创建一个tcp连接。</p>
<h3 id="http1-1" tabindex="-1"><a class="header-anchor" href="#http1-1"><span>http1.1</span></a></h3>
<p>发送一个请求tcp连接可以不关闭，再次发送请求可以复用这个连接，但是下一个请求必须等待前一个请求完成，下一个请求才能发送</p>
<h3 id="http2-0" tabindex="-1"><a class="header-anchor" href="#http2-0"><span>http2.0</span></a></h3>
<p>支持双向通信，服务端可以主动推送资源给服务,可以同时发送多个请求，且各个请求之间不存在阻塞关系，且不用按照顺序一一回应，且使用算法压缩了请求头，减少发送头部的数据量，同时报文改为二进制</p>
<h2 id="http2和websocket的区别" tabindex="-1"><a class="header-anchor" href="#http2和websocket的区别"><span>http2和websocket的区别</span></a></h2>
<p>HTTP/2引入了服务器推送，让服务器能够主动地推送资源到客户端缓存。然而它并没有允许推送数据到客户端应用本身。服务器的推送只是由浏览器来处理，并不会让应用代码介入，这也就意味着应用程序无法使用API来获取这些事件的通知。但是可以使用HTTP2+sse来进行双向通信。
从通信角度说：websocket可以主动推送数据给客户端，虽然http2也可以向客户端主动推送，但是他仍然需要客户端先发送一次请求，才能主动推送。从数据传输角度说：websocket无协议头传输效率更高。</p>
<h2 id="实验" tabindex="-1"><a class="header-anchor" href="#实验"><span>实验</span></a></h2>
<p>编写一个接口，被请求时从1开始每0.2s返回+1的数字，直到返回到100停止，编写另一个接口，用于停止立即停止这个返回过程</p>
<div class="language-java line-numbers-mode has-collapsed-lines collapsed" data-highlighter="shiki" data-ext="java" style="--vp-collapsed-lines:15;background-color:#282c34;color:#abb2bf"><pre class="shiki one-dark-pro vp-code" v-pre=""><code><span class="line"><span style="color:#C678DD">package</span><span style="color:#C678DD"> xyz.hmz.springbootdemo1.controller</span><span style="color:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> org.springframework.http.MediaType</span><span style="color:#ABB2BF">;</span></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> org.springframework.web.bind.annotation.GetMapping</span><span style="color:#ABB2BF">;</span></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> org.springframework.web.bind.annotation.PostMapping</span><span style="color:#ABB2BF">;</span></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> org.springframework.web.bind.annotation.RestController</span><span style="color:#ABB2BF">;</span></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> org.springframework.web.servlet.mvc.method.annotation.SseEmitter</span><span style="color:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> java.io.IOException</span><span style="color:#ABB2BF">;</span></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> java.util.concurrent.atomic.AtomicBoolean</span><span style="color:#ABB2BF">;</span></span>
<span class="line"><span style="color:#C678DD">import</span><span style="color:#E5C07B"> java.util.concurrent.atomic.AtomicInteger</span><span style="color:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#7F848E;font-style:italic">/**</span></span>
<span class="line"><span style="color:#7F848E;font-style:italic"> * @Author haomingze</span></span>
<span class="line"><span style="color:#7F848E;font-style:italic"> * @Date 2025/3/17 15:51</span></span>
<span class="line"><span style="color:#7F848E;font-style:italic"> * @description:</span></span>
<span class="line"><span style="color:#7F848E;font-style:italic"> */</span></span>
<span class="line"><span style="color:#ABB2BF">@</span><span style="color:#E5C07B">RestController</span></span>
<span class="line"><span style="color:#C678DD">public</span><span style="color:#C678DD"> class</span><span style="color:#E5C07B"> SseController</span><span style="color:#ABB2BF"> {</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C678DD">    private</span><span style="color:#C678DD"> static</span><span style="color:#E5C07B"> AtomicInteger</span><span style="color:#E06C75"> number </span><span style="color:#56B6C2">=</span><span style="color:#C678DD"> new</span><span style="color:#61AFEF"> AtomicInteger</span><span style="color:#E06C75">(</span><span style="color:#D19A66">1</span><span style="color:#E06C75">)</span><span style="color:#ABB2BF">;</span><span style="color:#7F848E;font-style:italic"> // 线程安全</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C678DD">    private</span><span style="color:#C678DD"> static</span><span style="color:#E5C07B"> AtomicBoolean</span><span style="color:#E06C75"> isStop </span><span style="color:#56B6C2">=</span><span style="color:#C678DD"> new</span><span style="color:#61AFEF"> AtomicBoolean</span><span style="color:#E06C75">(</span><span style="color:#D19A66">false</span><span style="color:#E06C75">)</span><span style="color:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#ABB2BF">    @</span><span style="color:#E5C07B">GetMapping</span><span style="color:#E06C75">(</span><span style="color:#D19A66">value</span><span style="color:#56B6C2"> =</span><span style="color:#98C379"> "/getNumbers"</span><span style="color:#ABB2BF">,</span><span style="color:#D19A66">produces</span><span style="color:#56B6C2"> =</span><span style="color:#E5C07B"> MediaType</span><span style="color:#ABB2BF">.</span><span style="color:#E5C07B">TEXT_EVENT_STREAM_VALUE</span><span style="color:#E06C75">)</span></span>
<span class="line"><span style="color:#C678DD">    public</span><span style="color:#E5C07B"> SseEmitter</span><span style="color:#61AFEF"> getNumbers</span><span style="color:#ABB2BF">()</span><span style="color:#ABB2BF"> {</span></span>
<span class="line"><span style="color:#E5C07B">        SseEmitter</span><span style="color:#E06C75"> emitter</span><span style="color:#56B6C2"> =</span><span style="color:#C678DD"> new</span><span style="color:#61AFEF"> SseEmitter</span><span style="color:#ABB2BF">();</span></span>
<span class="line"><span style="color:#C678DD">        new</span><span style="color:#61AFEF"> Thread</span><span style="color:#ABB2BF">(()</span><span style="color:#C678DD">-></span><span style="color:#ABB2BF">{</span></span>
<span class="line"><span style="color:#C678DD">            while</span><span style="color:#ABB2BF">(</span><span style="color:#E5C07B">number</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">get</span><span style="color:#ABB2BF">()</span><span style="color:#56B6C2">&#x3C;=</span><span style="color:#D19A66">100</span><span style="color:#56B6C2"> &#x26;&#x26;</span><span style="color:#56B6C2"> !</span><span style="color:#E5C07B">isStop</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">get</span><span style="color:#ABB2BF">()){</span></span>
<span class="line"><span style="color:#C678DD">                try</span><span style="color:#ABB2BF"> {</span></span>
<span class="line"><span style="color:#E5C07B">                    emitter</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">send</span><span style="color:#ABB2BF">(</span><span style="color:#E5C07B">number</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">getAndIncrement</span><span style="color:#ABB2BF">());</span></span>
<span class="line"><span style="color:#E5C07B">                    Thread</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">sleep</span><span style="color:#ABB2BF">(</span><span style="color:#D19A66">200</span><span style="color:#ABB2BF">);  </span></span>
<span class="line"><span style="color:#ABB2BF">                } </span><span style="color:#C678DD">catch</span><span style="color:#ABB2BF"> (</span><span style="color:#E5C07B">IOException</span><span style="color:#ABB2BF">|</span><span style="color:#E5C07B">InterruptedException</span><span style="color:#E06C75;font-style:italic"> e</span><span style="color:#ABB2BF">) {</span></span>
<span class="line"><span style="color:#E5C07B">                    emitter</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">complete</span><span style="color:#ABB2BF">();</span></span>
<span class="line"><span style="color:#C678DD">                    throw</span><span style="color:#C678DD"> new</span><span style="color:#61AFEF"> RuntimeException</span><span style="color:#ABB2BF">(e);</span></span>
<span class="line"><span style="color:#ABB2BF">                }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#ABB2BF">            }</span></span>
<span class="line"><span style="color:#E5C07B">            emitter</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">complete</span><span style="color:#ABB2BF">();</span></span>
<span class="line"><span style="color:#ABB2BF">        }).</span><span style="color:#61AFEF">start</span><span style="color:#ABB2BF">();</span></span>
<span class="line"><span style="color:#C678DD">        return</span><span style="color:#ABB2BF"> emitter;</span></span>
<span class="line"><span style="color:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="color:#ABB2BF">    @</span><span style="color:#E5C07B">PostMapping</span><span style="color:#E06C75">(</span><span style="color:#98C379">"/stopGetNumbers"</span><span style="color:#E06C75">)</span></span>
<span class="line"><span style="color:#C678DD">    public</span><span style="color:#C678DD"> void</span><span style="color:#61AFEF"> stopGetNumbers</span><span style="color:#ABB2BF">(){</span></span>
<span class="line"><span style="color:#E5C07B">        isStop</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">set</span><span style="color:#ABB2BF">(</span><span style="color:#D19A66">true</span><span style="color:#ABB2BF">);</span></span>
<span class="line"><span style="color:#E5C07B">        System</span><span style="color:#ABB2BF">.</span><span style="color:#E5C07B">err</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">println</span><span style="color:#ABB2BF">(</span><span style="color:#98C379">"断开连接成功"</span><span style="color:#ABB2BF">);</span></span>
<span class="line"><span style="color:#ABB2BF">    }</span></span>
<span class="line"><span style="color:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div><div class="collapsed-lines"></div></div><blockquote>
<p>参考：
https://www.ruanyifeng.com/blog/2018/03/http2_server_push.html<br>
https://blog.csdn.net/weixin_42560424/article/details/131380969</p>
</blockquote>
</div></template>


